home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / bsrc_p1.arc / F_SEND.C < prev    next >
Encoding:
C/C++ Source or Header  |  1988-11-30  |  31.9 KB  |  814 lines

  1. /*--------------------------------------------------------------------------*/
  2. /*               The Opus Computer-Based Conversation System                */
  3. /*       (c) Copyright 1986, Wynn Wagner III, All Rights Reserved           */
  4. /*                                                                          */
  5. /*         The original sealink protocol is copyrighted by SEA, inc.        */
  6. /*                                                                          */
  7. /*                 This module was written by W.Wagner III                  */
  8. /*        with modifications done by Bob Hartman and Rick Huebner           */
  9. /*                                                                          */
  10. /*                                                                          */
  11. /*        GENERAL PURPOSE FILE TRANSMITTER (Xmodem/YModem/Sealink)          */
  12. /*                                                                          */
  13. /*                                                                          */
  14. /*                                                                          */
  15. /*  This module is similar to a routine used by Opus-Cbcs (1.00).  It is    */
  16. /*  provided for your information only.  You will find routines that need   */
  17. /*  to be coded and identifiers to be resolved.                             */
  18. /*                                                                          */
  19. /*  There is absolutely no guarantee that anything here will work.  If you  */
  20. /*  break this routine, you own both pieces.                                */
  21. /*                                                                          */
  22. /*  USAGE:  You may use this material in any program with no obligation     */
  23. /*          as long as there is no charge for your program.  For more       */
  24. /*          information about commercial use, contact the "OPUSinfo HERE"   */
  25. /*          BBS (124/111).                                                  */
  26. /*                                                                          */
  27. /*                                                                          */
  28. /*--------------------------------------------------------------------------*/
  29. #include <sys\types.h>                                                              /*ww/870225*/
  30. #include <sys\stat.h>                                                               /*ww/870225*/
  31. #include <sys\timeb.h>
  32. #include <errno.h>
  33. #include <stdio.h>
  34. #include "xfer.h"
  35. #include "com.h"
  36.  
  37. extern byte *local_CEOL;
  38. extern int remote_capabilities;
  39. extern int daylight;
  40. extern long timezone;
  41. extern char *tzname[];
  42. extern int un_attended;
  43. extern int fullscreen;
  44.  
  45. int small_window = 0;
  46. int no_overdrive = 0;
  47.  
  48. static int send_ackless;
  49. static char *NOACKS_msg = "SEAlink Overdrive Disengaged";
  50.  
  51. char *ultoa();
  52.  
  53.  
  54.  
  55. /*--------------------------------------------------------------------------*/
  56. /* MULTI-PURPOSE FILE TRANSFER                                              */
  57. /*--------------------------------------------------------------------------*/
  58. int send_file( fname, protocol )
  59.    char *fname, protocol;
  60.    begin
  61.       register int         i;
  62.       register byte       *b;
  63.  
  64.       struct FILEINFO      dta;
  65.       struct zero_block   *header;
  66.       int                  in_char;
  67.       int                  ackblock;
  68.       int                  blknum;
  69.       unsigned int         last_block;
  70.       unsigned int         errs;
  71.       int                  sliding;
  72.       int                  base;
  73.       int                  head;
  74.       int                  block_size;
  75.       char                *buffer;
  76.       char                *malloc();
  77.       int                  do_chksum;
  78.       FILE                *fp;
  79.       char                *message;
  80.       long                 block_timer, timerset();
  81.       int                  win_size;
  82.       int                  full_window;
  83.       int                  may_be_seadog;
  84.       int                  ackerr;
  85.       struct stat st_stat;
  86.  
  87.       if (protocol == 'F')
  88.          {
  89.          protocol = 'S';
  90.          may_be_seadog = 1;
  91.          }
  92.       else
  93.          may_be_seadog = 0;
  94.       fp          = NULL;
  95.       sliding     =    0;
  96.       ackblock    =   -1;
  97.       do_chksum   = errs     =    0;
  98.       ackerr      =    0;
  99.  
  100.  
  101.       /*--------------------------------------------------------------------*/
  102.       /* The following window size works out to be between 3.5 and 4.5      */
  103.       /* seconds of data at any valid baud rate.  This gives us a set time  */
  104.       /* that the other end will wait before NAK'ing a block if it waits    */
  105.       /* to flush its buffer before NAK'ing.  If it does not wait, then it  */
  106.       /* does not matter very much except to make sure we only have a set   */
  107.       /* amount of run-ahead that will fit in a 4K buffer                   */
  108.       /*--------------------------------------------------------------------*/
  109.         full_window    = cur_baud/400;
  110.  
  111.       if (small_window && full_window > 6)
  112.          full_window = 6;
  113.  
  114.       XON_DISABLE();
  115.  
  116.       /*--------------------------------------------------------------------*/
  117.       /* Prepare file                                                       */
  118.       /*--------------------------------------------------------------------*/
  119.       if ((!fname) || (!fname[0]))     /* No file?  Just send an EOT.       */
  120.          begin
  121.  
  122.             CLEAR_INBOUND();
  123.  
  124.             for(i=0; i<5; i++)
  125.                begin
  126.                    switch( in_char=TIMED_READ(5) )
  127.                       begin
  128.  
  129.                         case 'C'    :
  130.                         case NAK    :
  131.                         case CAN    :  SENDBYTE(EOT);
  132.                                        break;
  133.  
  134.                         case TSYNC  :  return TSYNC;
  135.  
  136.                             default     :  if (in_char<' ') return 0;
  137.  
  138.                       end /* switch */
  139.                end
  140.             return 0;
  141.          end
  142.  
  143.       strlwr(fname);                                              /*ww/870225*/
  144.       CLEAR_IOERR();
  145.       if (!dfind(&dta, fname,0))  fp = fopen(fname,read_binary);
  146.       else errno  = ENOENT;
  147.  
  148.       if (got_error(OPEN_msg,fname))
  149.          begin
  150.             send_can();
  151.             return 0;
  152.          end
  153.  
  154.  
  155.       /*--------------------------------------------------------------------*/
  156.       /* Prepare buffer                                                     */
  157.       /*--------------------------------------------------------------------*/
  158.       buffer = malloc(1030);
  159.         header = (struct zero_block *)buffer;
  160.       if (!buffer)
  161.          begin
  162.             message = MEMOVFL_msg;
  163.             goto fubar;
  164.          end
  165.  
  166.  
  167.       /*--------------------------------------------------------------------*/
  168.       /* Prepare method                                                     */
  169.       /*--------------------------------------------------------------------*/
  170.       block_size  = 128;
  171.       head        = SOH;
  172.       switch(protocol)
  173.          begin
  174.             case 'Y' :  base=1; block_size=1024; head=STX;              break;
  175.             case 'X' :  base=1;                                         break;
  176.             case 'S' :  base=0;                                         break;
  177.             case 'T' :  base=0;                  head=SYN;              break;
  178.             case 'M' :  base=1;                                         break;
  179.             default  :  status_line("!Protocol?");                   return 0;
  180.          end
  181.       blknum= base;
  182.  
  183.       last_block = (int )((dta.size+((long )block_size-1L))/(long)block_size);
  184.  
  185.       if (un_attended && fullscreen)
  186.          {
  187.          clear_filetransfer();
  188.          gotoxy (0,12);
  189.          }
  190.       cprintf("\r\nSend %s (%d %c-blks)",fname,last_block,protocol);
  191.       set_xy( "Sending  " );
  192.  
  193.  
  194.       /*--------------------------------------------------------------------*/
  195.       /* Wait for signal to begin                                           */
  196.       /*--------------------------------------------------------------------*/
  197.       do
  198.          begin
  199.             i = TIMED_READ(5);
  200.             switch ( i )
  201.                begin
  202.                   case NAK :  /*--------------------------------------------*/
  203.                               /* NAK                                        */
  204.                               /*--------------------------------------------*/
  205.                               do_chksum = 1;
  206.                               /* fallthrough */
  207.  
  208.                   case 'C' :  /*--------------------------------------------*/
  209.                               /* CRC RESPONSE                               */
  210.                               /*--------------------------------------------*/
  211.                               begin
  212.                                   int send_tmp;
  213.                                   int send_tmp1;
  214.                                   if (((send_tmp = TIMED_READ(1))>=0)
  215.                                       &&((send_tmp1=TIMED_READ(1))==((~send_tmp)&0xff)))
  216.                                      begin
  217.                                         if (send_tmp <= 1)
  218.                                            sliding=1;
  219.                                         else
  220.                                            begin
  221.                                               /* Not a normal SEAlink startup    */
  222.                                               /* Lets end the transmission and   */
  223.                                               /* try again.  Nasty, but it helps */
  224.                                               SENDBYTE (EOT);
  225.                                               continue;
  226.                                            end
  227.                                      end
  228.                                   if (may_be_seadog)
  229.                                      {
  230.                                      sliding = 1;
  231.                                      }
  232.                                   errs = 0;
  233.                                   CLEAR_INBOUND();
  234.                                   throughput(0,0L);
  235.                                   goto sendloop;
  236.                               end
  237.  
  238.                   case CAN :  /*--------------------------------------------*/
  239.                               /* CANCEL                                     */
  240.                               /*--------------------------------------------*/
  241.                               message = CAN_msg;
  242.                               goto fubar;
  243.  
  244.                   default  :  /*--------------------------------------------*/
  245.                               /* OTHER RESPONSES (debris)                   */
  246.                               /*--------------------------------------------*/
  247.                               if (((KEYPRESS()) and (READKB()==27)))
  248.                                  begin
  249.                                     message = KBD_msg;
  250.                                     goto fubar;
  251.                                  end
  252.  
  253.                               else if ( (errs++)>15 )
  254.                                  begin
  255.                                     message = TIME_msg;
  256.                                     goto fubar;
  257.                                  end
  258.                               block_timer = timerset (50);
  259.                               while (!timeup (block_timer))
  260.                                  time_release();
  261.                               CLEAR_INBOUND();
  262.  
  263.                end /* switch */
  264.  
  265.          end /* wait for signal to begin */
  266.       while(CARRIER);
  267.  
  268.       message = CARRIER_msg;
  269.       goto fubar;
  270.  
  271.  
  272.       /*--------------------------------------------------------------------*/
  273.       /* Transfer                                                           */
  274.       /*--------------------------------------------------------------------*/
  275. sendloop:
  276.       while(CARRIER)
  277.          begin
  278.  
  279.             message  = NULL;
  280.             win_size = (blknum<2) ? 2 : (send_ackless ? 220 : full_window);
  281.  
  282.             if (((KEYPRESS()) and (READKB()==27)))
  283.                begin
  284.                   message = KBD_msg;
  285.                   goto fubar;
  286.                end
  287.  
  288.             if (blknum <= last_block)
  289.                begin
  290.                   /*--------------------------------------------------------*/
  291.                   /* DATA                                                   */
  292.                   /*--------------------------------------------------------*/
  293.                   memset( buffer, 0, block_size );
  294.                   if (blknum)
  295.                      begin
  296.                         errno = 0;
  297.                         fseek( fp, ((long)(blknum-1)*(long)block_size), 0);
  298.                         if (got_error(READ_msg,fname))
  299.                            begin
  300.                               message = SEEK_msg;
  301.                               goto fubar;
  302.                            end
  303.                   
  304.                         errno = 0;
  305.                         fread( buffer, block_size, 1, fp );
  306.                         if (got_error(READ_msg,fname))
  307.                            begin
  308.                               message = READ_msg;
  309.                               goto fubar;
  310.                            end
  311.                      end
  312.                   else 
  313.                      begin
  314.                         block_size   = 128;
  315.                         header->size = dta.size;
  316.                         stat (fname, &st_stat);
  317.                         tzset();
  318.                         header->time = st_stat.st_atime-timezone;
  319.  
  320.                         stcgfn( header->name, dta.name );
  321.  
  322.                         if (protocol=='T')
  323.                            begin
  324.                               for(i=0; i<HEADER_NAMESIZE; i++)
  325.                                  if (!(header->name[i])) header->name[i] = ' ';
  326.                               header->time = dta.time;
  327.                            end
  328.  
  329.                         strcpy( header->moi,  xfer_id );
  330.                         if ((cur_baud >= 9600) && (sliding))
  331.                            {
  332.                            header->noacks = 1;
  333.                            send_ackless = 1;
  334.                            }
  335.                         else
  336.                            {
  337.                            header->noacks = 0;
  338.                            send_ackless = 0;
  339.                            }
  340.  
  341.                         if (no_overdrive)
  342.                            {
  343.                            header->noacks = 0;
  344.                            send_ackless = 0;
  345.                            }
  346.                      end
  347.       
  348.                   /*--------------------------------------------------------*/
  349.                   /* HEAD                                                   */
  350.                   /*--------------------------------------------------------*/
  351.                   SENDBYTE(  head   );
  352.                   SENDBYTE(  blknum );
  353.                   SENDBYTE( ~blknum );
  354.       
  355.       
  356.                   /*--------------------------------------------------------*/
  357.                   /* SEND                                                   */
  358.                   /*--------------------------------------------------------*/
  359.                   b = buffer;
  360.                   SENDCHARS (b, block_size, 1);
  361.  
  362.  
  363.                   /*--------------------------------------------------------*/
  364.                   /* CHECK                                                  */
  365.                   /*--------------------------------------------------------*/
  366.                   if ((do_chksum)||(head==SYN))
  367.                      begin
  368.                         unsigned char chksum = '\0';
  369.                         for ( b=buffer,i=0; i<block_size; i++, b++ )
  370.                            chksum+=(*b);
  371.                         SENDBYTE( chksum );
  372.                      end
  373.                   else
  374.                      begin
  375.                         word crc;
  376.  
  377.                         for(b=buffer, crc=i=0; i<block_size; i++, b++)
  378.                            crc = xcrc(crc,(byte )(*b));
  379.  
  380.                         SENDBYTE( crc>>8   );
  381.                         SENDBYTE( crc&0xff );
  382.                      end
  383.                end /* if not finished */
  384.  
  385.             /*--------------------------------------------------------------*/
  386.                 /* Only wait 30 seconds for a response                          */
  387.                 /* For non-sliding this number is updated, for sliding we have     */
  388.                 /*    a problem since the output buffer may still have stuff in     */
  389.                 /*    it.  We need to make sure we reset this when output is done  */
  390.                 /* in the sliding case.  What we actually do is reset it if the */
  391.                 /* output has not yet completed.  We only check it in the case  */
  392.                 /* of debris, then recycle, so this should be a reasonable way  */
  393.                 /* of doing things in the sliding case.                         */
  394.             /*--------------------------------------------------------------*/
  395.                 block_timer = timerset(3000);
  396.  
  397. slide_reply:
  398.             /*--------------------------------------------------------------*/
  399.                 /* If we are not sliding, force the output and purge the input. */
  400.                 /* This is simply good Xmodem practice.  It is also necessary   */
  401.                 /* to make sure that the other end has received all of the data */
  402.                 /* before starting the block reply timeout.                     */
  403.             /*--------------------------------------------------------------*/
  404.                 if (!sliding)
  405.                     begin
  406. /*
  407.                         CLEAR_INBOUND();
  408. */
  409.                         while (!OUT_EMPTY())
  410.                             time_release();
  411.                         block_timer = timerset(3000);
  412.                     end
  413.  
  414.             /*--------------------------------------------------------------*/
  415.             /* REPLY: Slide                                                 */
  416.             /*        Don't wait, unless other end has something to say     */
  417.             /*        or we're at/beyond the window.                        */
  418.             /*--------------------------------------------------------------*/
  419.             else if ( (blknum    < (ackblock+win_size)) and /* in window    */
  420.                       (blknum    < last_block   ) and /* have more to send  */
  421.                       (PEEKBYTE()< 0 )                /* other end is quiet */
  422.                     )
  423.                begin
  424.                  if ((send_ackless) && (blknum > 0))
  425.                     {
  426.                     ackblock = blknum;
  427.  
  428.                     if (++blknum > last_block)
  429.                        {
  430.                        goto done;
  431.                        }
  432.  
  433.                     if ((blknum % 20) == 0)
  434.                        {
  435.                        gotoxy(locate_x,locate_y);
  436.                        cputs( ultoa(((unsigned long )(blknum)),e_input,10) );
  437.                        bdos (9,"*$");
  438.                        }
  439.                     }
  440.                  else
  441.                     {
  442.                     blknum++;
  443.                     }
  444.                  goto sendloop;
  445.                end
  446.  
  447.            if (PEEKBYTE() < 0)
  448.               {
  449.               if (send_ackless)
  450.                  {
  451.                  ackblock = blknum;
  452.  
  453.                  if (++blknum > last_block)
  454.                     {
  455.                     goto done;
  456.                     }
  457.  
  458.                  if ((blknum % 20) == 0)
  459.                     {
  460.                     gotoxy(locate_x,locate_y);
  461.                     cputs( ultoa(((unsigned long )(blknum)),e_input,10) );
  462.                     bdos (9,"*$");
  463.                     }
  464.  
  465.                  goto sendloop;
  466.                  }
  467.               }
  468.  
  469.  
  470.             /*--------------------------------------------------------------*/
  471. reply:      /* REPLY: Wait state                                            */
  472.             /*        No sliding, or slid too far.  Wait for a reply.       */
  473.             /*                                                              */
  474.                 /* If we got here we are either not sliding, or we are sliding  */
  475.                 /* and have received an input character, or we are sliding and  */
  476.                 /* have slid too far.  In the first case the following loop     */
  477.                 /* will not do anything because the output is empty, in the     */
  478.                 /* second case we also will not do anything since we have an    */
  479.                 /* input character ready, in the final case we want to execute  */
  480.                 /* the loop since we are in a wait state.  The loop will go on  */
  481.                 /* until the output is empty (in the worst case), and since we  */
  482.                 /* we have disabled flow control here (right???) we will never  */
  483.                 /* have to worry about the loop not terminating.  Now, we just  */
  484.                 /* sit and loop as long as there is output to do and no input.  */
  485.                 /* Just to make wwIII happy do a time_release() so that his     */
  486.                 /* DDos system will be more efficient!                          */
  487.             /*--------------------------------------------------------------*/
  488.  
  489.                 while ( (!OUT_EMPTY()) and
  490.                           (PEEKBYTE()<0))
  491.                     time_release();  /* ... time slice routine for multi-taskers */
  492.  
  493.             /*--------------------------------------------------------------*/
  494.                 /* If we got here we either sent all the output, or got input.  */
  495.                 /* In the first case we should get a response within 15 seconds */
  496.                 /* In the second case we should get an immediate response.      */
  497.                 /* Either way, nothing in 30 seconds is a timeout               */
  498.             /*--------------------------------------------------------------*/
  499.             if ((in_char=TIMED_READ(30))<0)
  500.                begin
  501.                   message = TIME_msg;
  502.                   goto fubar;
  503.                end
  504.  
  505.             if (in_char=='C')
  506.                begin
  507.                   do_chksum = 0;
  508.                   in_char   = NAK;
  509.                end
  510.  
  511.  
  512.             /*--------------------------------------------------------------*/
  513.             /* CAN                                                          */
  514.             /*--------------------------------------------------------------*/
  515.             if (in_char==CAN)
  516.                begin
  517.                   message = CAN_msg;
  518.                   goto fubar;
  519.                end
  520.  
  521.  
  522.             /*--------------------------------------------------------------*/
  523.             /* REPLY: Take action based on slide-response                   */
  524.             /*--------------------------------------------------------------*/
  525.             if ((in_char>0) and (sliding))
  526.                begin
  527.  
  528.                   register int i, j;
  529.  
  530.                   if (++ackerr >= 10)
  531.                      {
  532.                      if (send_ackless)
  533.                         {
  534.                         send_ackless = 0;
  535.                         message = NOACKS_msg;
  536.                         }
  537.                      }
  538.  
  539.                   if ((in_char==ACK) || (in_char==NAK))
  540.                      begin
  541.                         if ((i=TIMED_READ(2))<0)
  542.                            begin
  543.                               sliding=0;
  544.                               if (send_ackless)
  545.                                  {
  546.                                  send_ackless = 0;
  547.                                  message = NOACKS_msg;
  548.                                  }
  549.                            end
  550.                         else
  551.                            begin
  552.                               if ((j=TIMED_READ(2))<0)
  553.                                  begin
  554.                                     sliding = 0;
  555.                                     if (send_ackless)
  556.                                        {
  557.                                        send_ackless = 0;
  558.                                        message = NOACKS_msg;
  559.                                        }
  560.                                  end
  561.                               else if (i==(j^0xff))
  562.                                  begin
  563.                                     i = blknum-((blknum-i)&0xff);
  564.                                     if ((i<=blknum)&&(i>(blknum-win_size-10)))
  565.                                        begin
  566.                                           if (in_char==ACK)
  567.                                              begin
  568.                                                 ackblock=i;
  569.                                                 blknum++;
  570.                                                 if (ackblock>=last_block)
  571.                                                    begin
  572.                                                       goto done;
  573.                                                    end
  574.                                                 errs = 0;
  575.  
  576.                                                 if ((head==SYN)&&(blknum))
  577.                                                    head = SOH; /* ZapTeLink */
  578.  
  579.                                              end
  580.                                           else
  581.                                              begin
  582.                                                 blknum=i;
  583.                                                 /*CLEAR_INBOUND();*/
  584.                                                 CLEAR_OUTBOUND();
  585.                                                 errs++;
  586.                                              end
  587.                                        end
  588.                                  end
  589.                               else
  590.                                  begin
  591.                                     message = "SLIDE CMPL ERR";
  592.                                  end
  593.                            end
  594.                      end
  595.                   else
  596.                      begin
  597.  
  598.                             /*--------------------------------------------------*/
  599.                                 /* If we got debris, just ignore it and go on if we */
  600.                                 /* have not yet had a timeout.  If we timed out,    */
  601.                                 /* then just go to the fubar label and abort        */
  602.                             /*--------------------------------------------------*/
  603.  
  604.                         gotoxy(locate_x+10,locate_y);
  605.                         cprintf(" Debris [%Xh]",in_char);
  606.  
  607.  
  608.                             /*--------------------------------------------------*/
  609.                                 /* The error is timeout with the output buffer      */
  610.                                 /* empty (we can't penalize someone for a timeout   */
  611.                                 /* if we haven't yet sent them all they need!!!     */
  612.                             /*--------------------------------------------------*/
  613.  
  614.                                 if (timeup(block_timer) and OUT_EMPTY())
  615.                                     begin
  616.                                         message = TIME_msg;
  617.                                         goto fubar;
  618.                                     end
  619.  
  620.                             /*--------------------------------------------------*/
  621.                                 /* Ok, we either have a timeout or the buffer still */
  622.                                 /* has stuff in it.  If it still has stuff, reset   */
  623.                                 /* the timeout variable before trying again         */
  624.                             /*--------------------------------------------------*/
  625.  
  626.                                 else if (!OUT_EMPTY()) block_timer = timerset(3000);
  627.  
  628.                                 goto slide_reply;
  629.                      end
  630.                end
  631.  
  632.             /*--------------------------------------------------------------*/
  633.             /* REPLY: Take action based on regular response                 */
  634.             /*--------------------------------------------------------------*/
  635.             if (!sliding)
  636.                begin
  637.                   if (in_char==ACK)
  638.                      begin
  639.  
  640.                         /*--------------------------------------------------*/
  641.                         /* On block 10, throw in an extra pause to give the */
  642.                         /* other end a change to fall into a slide if it    */
  643.                         /* feels it's something it needs to do.             */
  644.                         /*--------------------------------------------------*/
  645.                         if (blknum==10) timer(3);   /* approx. 3/10s second */
  646.  
  647.                         /*--------------------------------------------------*/
  648.                         /* Smell the other system vis-a-vis a slide.        */
  649.                         /*--------------------------------------------------*/
  650.                         if (PEEKBYTE()>0)
  651.                            begin
  652.                               int send_tmp;
  653.                               if (((send_tmp = TIMED_READ(1))>=0)
  654.                                    &&(TIMED_READ(1)==((~send_tmp)&0xff)))
  655.                                  begin
  656.                                     sliding  =  1;
  657.                                     ackblock =  send_tmp;
  658.                                  end
  659.                            end
  660.                         /*if (!sliding) CLEAR_INBOUND();*/
  661.  
  662.  
  663.                         message = NULL;
  664.                         if (blknum>=last_block) goto done;
  665.                         blknum++;
  666.  
  667.                         if ((head==SYN)&&(blknum)) head = SOH; /* ZapTeLink */
  668.  
  669.                         errs = 0;
  670.                      end
  671.                   else if (in_char==NAK)
  672.                      begin
  673.                         errs++;
  674.                         timer(5);
  675.                         /*CLEAR_INBOUND();*/
  676.                         CLEAR_OUTBOUND();
  677.                         message = NAK_msg;
  678.                      end
  679.                   else if (CARRIER)
  680.                             begin
  681.                                 /* Did we time out yet? */
  682.                                 if (!timeup(block_timer))
  683.                                     goto reply;
  684.                                 else
  685.                                     begin
  686.                                         message = TIME_msg;
  687.                                         goto fubar;
  688.                                     end
  689.                             end
  690.                         else
  691.                             begin
  692.                                 message = CARRIER_msg;
  693.                                 goto fubar;
  694.                             end
  695.                end
  696.  
  697.             if (errs>10)
  698.                begin
  699.                   message = FUBAR_msg;
  700.                   goto fubar;
  701.                end
  702.  
  703. bottom:     gotoxy(locate_x,locate_y);
  704.               i  = (blknum<=last_block)?blknum:last_block;
  705.             cputs( ultoa(((unsigned long )(i)),e_input,10) );
  706.  
  707.             if ((sliding) and (ackblock>0))
  708.                begin
  709.                   if (send_ackless)
  710.                      bdos (9,"*$");
  711.                   else
  712.                      {
  713.                      bdos(9," : $");
  714.                      cputs( ultoa(((unsigned long )(ackblock)),e_input,10) );
  715.                      }
  716.                end
  717.  
  718.             if (message)
  719.                begin
  720.                   putch(' ');
  721.                   cputs( message );
  722.                   cputs( local_CEOL );
  723.                end
  724.  
  725.          end /* while */
  726.  
  727.       message = CARRIER_msg;
  728.  
  729.  
  730.  
  731. fubar:
  732.  
  733.       CLEAR_OUTBOUND();
  734.       send_can();
  735.  
  736.       status_line("!%s not sent: %s",fname,message);
  737.  
  738.       if (fp)     fclose(fp);
  739.       if (buffer) free(buffer);
  740.       /*CLEAR_INBOUND();*/
  741.  
  742.       return 0;
  743.  
  744.  
  745. done:
  746.       while (!OUT_EMPTY())
  747.          time_release();
  748.  
  749.       if (fp)     fclose(fp);
  750.       if (buffer) free(buffer);
  751.  
  752.       /* Here I am going to delay some to make sure everything is cool */
  753.       if (cur_baud > 2400)
  754.          {
  755.          block_timer = timerset (200);
  756.          while (CARRIER && !timeup (block_timer))
  757.             time_release();
  758.          }
  759.  
  760.       CLEAR_INBOUND();
  761.       SENDBYTE (EOT);
  762.  
  763.       ackerr = 1;
  764.  
  765.       for(i=0; i<5; i++)
  766.          begin
  767.             if (!CARRIER)
  768.                {
  769.                ackerr = 1;
  770.                goto gohome;
  771.                }
  772.  
  773.             switch( TIMED_READ(5) )
  774.                begin
  775.  
  776.                   case 'C':
  777.                   case NAK:
  778.                   case CAN:
  779.                               if (sliding && ((in_char = TIMED_READ(1)) >= 0))
  780.                                  {
  781.                                  TIMED_READ(1);
  782.                                  }
  783.                               CLEAR_INBOUND();
  784.                               SENDBYTE(EOT);
  785.                                  break;
  786.  
  787.                   case TSYNC: ackerr = TSYNC;
  788.                               goto gohome;
  789.  
  790.                   case ACK:
  791.                               if (sliding && ((in_char = TIMED_READ(1)) >= 0))
  792.                                  {
  793.                                  TIMED_READ(1);
  794.                                  }
  795.                               ackerr = 1;
  796.                               goto gohome;
  797.  
  798.                end /* switch */
  799.          end
  800.  
  801. gohome:
  802.  
  803.       if (locate_y>1) gotoxy(0,locate_y-1);
  804.       throughput(1,dta.size);
  805.  
  806.       status_line( "+Sent-S %s", fname );
  807.  
  808.       return ackerr;
  809.  
  810.    end
  811.  
  812.  
  813. /* END OF FILE: F_Send.C */
  814.